package cn.st4rlight.util.enums;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

import org.apache.commons.collections4.CollectionUtils;

import com.google.common.collect.Maps;

import cn.st4rlight.util.collection.TransformUtil;
import cn.st4rlight.util.enums.items.EnumReqType;
import cn.st4rlight.util.enums.query.QueryEnumDescReq;
import cn.st4rlight.util.enums.query.SingleEnumVO;
import cn.st4rlight.util.value.SafeUtil;
import lombok.SneakyThrows;

/**
 * @author st4rlight <st4rlight@163.com>
 * Created on 2025-09-15
 */
public class EnumQueryUtil {

    // 枚举信息缓存
    private static final Map<EnumReqType, List<SingleEnumVO>> REQ_ENUM_CACHE =
            TransformUtil.toMap(EnumReqType.values(), Function.identity(), EnumQueryUtil::buildEnumListByReq);

    /**
     * 根据指定查询条件获取枚举信息
     */
    public static Map<String, List<SingleEnumVO>> queryEnumDesc(QueryEnumDescReq req) {
        Set<String> enumReqTypes = req.getEnumReqTypes();
        if (CollectionUtils.isEmpty(enumReqTypes)) {
            return Collections.emptyMap();
        }

        Map<String, List<SingleEnumVO>> resultMap = Maps.newHashMap();
        for (String enumReqKey : enumReqTypes) {
            EnumReqType enumReqType = EnumReqType.nameOf(enumReqKey);
            if (EnumReqType.UNKNOWN.equals(enumReqType)) {
                continue;
            }
            List<SingleEnumVO> tempList = SafeUtil.of(REQ_ENUM_CACHE.get(enumReqType));
            resultMap.put(enumReqKey, tempList);
        }
        return resultMap;
    }

    /**
     * EnumReqType --> 对应的枚举值列表
     */
    @SneakyThrows
    private static List<SingleEnumVO> buildEnumListByReq(EnumReqType enumReqType) {
        if (EnumReqType.UNKNOWN.equals(enumReqType)) {
            return Collections.emptyList();
        }
        // 获取对应的枚举类
        Class<? extends Enum<? extends HasCodeAndDesc>> enumClass = enumReqType.getEnumClass();
        if (Objects.isNull(enumClass)) {
            return Collections.emptyList();
        }

        // 通过反射调用 values 方法
        Method valuesMethod = enumClass.getDeclaredMethod("values");
        Enum<? extends HasCodeAndDesc>[] enumValues =
                (Enum<? extends HasCodeAndDesc>[]) valuesMethod.invoke(enumClass);
        // 遍历枚举值
        return Arrays.stream(enumValues)
                .filter(item -> ((HasCodeAndDesc) item).getCode() != 0 || enumReqType.isAllowZero())
                .map(EnumQueryUtil::buildSingleEnumVO)
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 枚举 HasCodeAndDesc --> SingleEnumVO
     */
    public static SingleEnumVO buildSingleEnumVO(Enum<? extends HasCodeAndDesc> enumValue) {
        HasCodeAndDesc hasCodeAndDesc = (HasCodeAndDesc) enumValue;
        return new SingleEnumVO()
                .setCode(hasCodeAndDesc.getCode())
                .setKey(enumValue.name())
                .setDesc(hasCodeAndDesc.getDesc());
    }
}
